#ifndef __K_ICM42686_H__
#define __K_ICM42686_H__

#include <linux/regmap.h>
#include <linux/iio/iio.h>


#ifndef M_PI
  #define M_PI 3.14159265358979323846f
#endif 

#define ICM42686_ID        0x44        /* ID值 */

/**
 * Definition of Register Addr
 */
typedef enum {
	//FOR ICM42686 register
	DEVICE_CONFIG		= 0x11, //device_config(spi_mode,soft_reset_config),page 61 of 105
	PWR_MGMT0			= 0x4E, //page 72 of 105
	GYRO_CONFIG0        = 0x4F, //GYRO_FS_SEL[bit5-7],GYRO_ODR[bit0-3],page 58 of 105
	ACCEL_CONFIG0       = 0x50, //page 74 of 105
	GYRO_CONFIG1        = 0x51, //temperature LPF  and gyro UI filter and DEC2_M2 filter order,page 75 of 105
	GYRO_ACCEL_CONFIG0  = 0x52, //set gyro and accel LPF bandwidth
	ACCEL_CONFIG1       = 0x53, //page 77 of 105
	TMST_CONFIG         = 0x54, //page 77 of 105
	FIFO_CONFIG1        = 0x5F, //page 79 of 105
	FIFO_CONFIG2        = 0x60, //page 79 of 105
	FIFO_CONFIG3        = 0x61, //page 79 of 105
	FSYNC_CONFIG		= 0x62,
	WHO_AM_I            = 0x75, //page 84 of 105
	REG_BANK_SEL 		= 0x76, //page 84 of 105
	TEMP_OUT_ADDR		= 0x1D, // temperature
	ACCEL_OUT_ADDR		= 0x1F, //page 58 of 105 // 0x1F for ACCEL_DATA_X1(X0,Y1,Y0,Z1,Z0)
	GYRO_OUT_ADDR		= 0x25, // GYRO_DATA_X1

	//interrupt and FIFO reg config
	INT_CONFIG			= 0x14,
	FIFO_CONFIG			= 0x16,
	FIFO_SOURCE0		= 0x65,
	INTF_CONFIG0		= 0x4C,
	INT_CONFIG0			= 0x63,
	INT_CONFIG1			= 0x64,
	INT_SOURCE0			= 0x65,
	INT_SOURCE1			= 0x66,
	INT_SOURCE3			= 0x68,
	///end of register
} E_GYRO_REG_ADDR;

/**
 * Definition of Register Data
 */
typedef enum {
	// CONFIG register
	#define DLPF(v) 	((v) << 0)	// For the DLPF to be used, FCHOICE_B[1:0] is 2â€™b00.
	FSYNC_TEMP			= (1 << 3),
	FSYNC_GYRO_X		= (2 << 3),
	FSYNC_GYRO_Y		= (3 << 3),
	FSYNC_GYRO_Z		= (4 << 3),
	FSYNC_ACCEL_X		= (5 << 3),
	FSYNC_ACCEL_Y		= (6 << 3),
	FSYNC_ACCEL_Z		= (7 << 3),
	FIFO_DROP			= (1 << 6),
	FIFO_REPLACE		= (0 << 6),
	// GYRO_CONFIG register
	FCHOICE_B_x1		= (1 << 0),
	FCHOICE_B_10		= (2 << 0),
	FCHOICE_B_00		= (0 << 0),
	GYRO_FS_250 		= (0 << 3),
	GYRO_FS_500 		= (1 << 3),
	GYRO_FS_1000		= (2 << 3),
	GYRO_FS_2000		= (3 << 3),
	// ACCEL_CONFIG register
	ACCEL_FS_2G 		= (0 << 3),
	ACCEL_FS_4G 		= (1 << 3),
	ACCEL_FS_8G 		= (2 << 3),
	ACCEL_FS_16G		= (3 << 3),
	ACCEL_DEC2_4		= (0 << 4),
	ACCEL_DEC2_8		= (1 << 4),
	ACCEL_DEC2_16		= (2 << 4),
	ACCEL_DEC2_32		= (3 << 4),
	// ACCEL_CONFIG2 register
	ACCEL_FCHOICE_B_1	= (1 << 3),
	ACCEL_FCHOICE_B_0	= (0 << 3),
	// INT_PIN_CFG register
	INT_FSYNC_EN		= (1 << 2), // FSYNC causes the interrupt
	INT_FSYNC_LOW		= (1 << 3), // FSYNC is active low
	INT_FSYNC_HIGH		= (0 << 3), // FSYNC is active high
	INT_RD2CLEAR		= (1 << 4), // any read clears interrupt status
	INT_PULSE			= (0 << 5), // interrupt is a 50us pulse
	INT_LATCH			= (1 << 5), // level is held until interrupt status is cleared
	INT_PUSHPULL		= (0 << 6), // INT pin is push-pull
	INT_OPEN			= (1 << 6), // INT pin is open drain
	INT_HIGH			= (0 << 7), // INT pin is active high
	INT_LOW 			= (1 << 7), // INT pin is active low
	// INT_ENABLE, INT_STATUS registers
	INT_RAW_RDY 		= (1 << 0),
	INT_GDRIVE			= (1 << 2),
	INT_FSYNC			= (1 << 3),
	INT_OVERFLOW		= (1 << 4),
	INT_WOM_Z			= (1 << 5),
	INT_WOM_Y			= (1 << 6),
	INT_WOM_X			= (1 << 7),
	INT_WOM 			= (INT_WOM_X | INT_WOM_Y | INT_WOM_Z),
	// USER_CTRL register
	CTRL_SIG_RST		= (1 << 0),
	CTRL_FIFO_RST		= (1 << 2),
	CTRL_FIFO_EN		= (1 << 6),
	// FIFO_EN register
	FIFO_ACCEL			= (1 << 3),
	FIFO_GYRO	 		= (1 << 4),
	// PWR_MGMT_1 register
	PWR_CLK_OSC 		= (0 << 0),
	PWR_CLK_PLL1		= (1 << 0),
	PWR_SLEEP			= (1 << 6),
	PWR_RESET			= (1 << 7),
	// SIGNAL_PATH_RESET register
	RESET_TEMP			= (1 << 0),
	RESET_ACCEL 		= (1 << 1),

	//ICM42686 register data
	SOFT_RESET_B0		= (1 << 0),
	BANK0_B0			= (0 << 0),
	GYRO_CONFIG0_DATA	= 0x03,//+-2000dps(default/8KHz)
	GYRO_CONFIG1_DATA	= 0X06,//1st order
	ACCEL_CONFIG0_DATA	= 0x06,
	ACCEL_CONFIG1_DATA	= 0x00,
	GYRO_ACCEL_CONFIG0_DATA = 0x00,
	PWR_MGMT0_DATA		= 0x0F,//
	FIFO_CONFIG1_DATA	= 0x03,
} E_GYRO_REG_DATA;


#define ICM42686_CHAN(_type, _channel2, _si) \
	{ \
		.type = (_type), \
		.modified = 1, \
		.channel2 = (_channel2), \
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
			BIT(IIO_CHAN_INFO_CALIBBIAS), \
		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
		.scan_index = (_si), \
		.scan_type = { \
			.sign = 's', \
			.realbits = 16, \
			.storagebits = 16, \
			.shift = 0, \
			.endianness = IIO_BE, \
		}, \
	}

#define ICM42686_TEMP_CHAN(_type, _si) \
	{ \
		.type = (_type), \
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
			BIT(IIO_CHAN_INFO_OFFSET) | \
            BIT(IIO_CHAN_INFO_SCALE), \
		.scan_index = (_si), \
		.scan_type = { \
			.sign = 's', \
			.realbits = 16, \
			.storagebits = 16, \
			.shift = 0, \
			.endianness = IIO_BE, \
		}, \
	}

/*
 * @brief ICM42686的扫描元素
 * 3轴加速度计、3轴陀螺仪、1路温度传感器、1路时间戳
 */
enum icm42686_scan {
    ICM42686_SCAN_ACCEL_X,
    ICM42686_SCAN_ACCEL_Y,
    ICM42686_SCAN_ACCEL_Z,
    ICM42686_SCAN_TEMP,
    ICM42686_SCAN_GYRO_X,
    ICM42686_SCAN_GYRO_Y,
    ICM42686_SCAN_GYRO_Z,
    ICM42686_SCAN_TIMESTAMP,
};

/*
 * @brief: struct icm42686
 * @spi:  SPI设备
 * @regmap: 
 * @regmap_cfg: 
 * @lock:
 */
struct icm42686 {
    struct spi_device   *spi;
    struct regmap       *regmap;
    struct regmap_config regmap_cfg;
    struct mutex         lock;
};

/*
 * icm42686数据
 * @acc: 加速度计值
 * @gyro: 陀螺仪值
 */
struct icm42686_data {
	struct _acc
	{
		u16 x;
		u16 y;
		u16 z;
	}acc;

	struct _gyro
	{
		u16 x;
		u16 y;
		u16 z;
	}gyro;
};


int icm42686_get_data_front(struct iio_dev * iio, struct icm42686_data * imu);
int icm42686_get_data_bottom(struct icm42686 *dev, struct icm42686_data * imu);


#endif /* __K_ICM42686_H__ */
